#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "base64.h"

void base64_test_file(void)
{
	char *encode = NULL;
	char *decode = NULL;

    //二进制数据（一张图片）编解码测试
	printf("\n\nfile base64 encode/decode test:\n");

    //以二进制读取模式打开文件
    FILE *fp = fopen("./input.jpg", "rb");
    if (fp == NULL) {
        printf("Failed to open file: ./test.jpg\n");
        return;
    }

    //获取文件大小
    fseek(fp, 0, SEEK_END);
    int file_len = ftell(fp);

    //将文件读入file_content中
    fseek(fp, 0, SEEK_SET);
    char *file_content = malloc(file_len);
    fread(file_content, file_len, 1, fp);

    //关闭文件
    fclose(fp);

    //文件内容进行编码
    encode = base64_encode(file_content, file_len);
    free(file_content);

    //printf("  encode(./input.jpg) => %s\n", encode);
    printf("  encode(./input.jpg) success\n");

    //base64编码后的文本解码出原始数据
    int decode_len = 0;
    decode = base64_decode(encode, &decode_len);
    //printf("  decode(\"%s\") => %s, len:%d\n", encode, decode, decode_len);
    printf("  decode(encode(./input.jpg)) => ./output.jpg\n");

    printf("check md5:\n");
    system("md5sum input.jpg output.jpg");

    //将解码得到的原始数据保存到新文件中
    fp = fopen("./output.jpg", "wb");
    if (fp == NULL) {
        printf("Failed to open file: ./output.jpg\n");
        goto _exit_direct;
    }
    fwrite(decode, decode_len, 1, fp);
    fclose(fp);

_exit_direct:
    if (encode) {
        free(encode);
        encode = NULL;
    }

    if (decode) {
        free(decode);
        decode = NULL;
    }
}

void base64_test_buffer(void)
{
    int i = 0;
    char *encode = NULL;
	char *decode = NULL;

    //二进制数据编解码测试
	printf("\n\nBinary buffer base64 encode/decode test:\n");

    char buffer[] = {0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x7d};

    //buffer内容进行编码
    encode = base64_encode(buffer, sizeof(buffer));
    printf("  encode(");
    for (i = 0; i < sizeof(buffer); i++) {
        printf("%#hhx ", buffer[i]);
    }
    printf(") => %s\n", encode);

    //base64编码后的文本解码出原始数据
    int decode_len = 0;
    decode = base64_decode(encode, &decode_len);
    printf("  decode(\"%s\") => ", encode);
    for (i = 0; i < decode_len; i++) {
        printf("%#hhx ", decode[i]);
    }
    printf("\n");

    if (encode) {
        free(encode);
        encode = NULL;
    }

    if (decode) {
        free(decode);
        decode = NULL;
    }
}

void base64_test_string(void)
{
    int i = 0;
    char *encode = NULL;
    char *decode = NULL;

    //字符串编解码测试
    printf("\n\nstring base64 encode/decode test:\n");
    char *src[] = {"a", "ab", "abc", "abcd", "abcde", "abcdef", "abcdefg", "abcdefgh", "abcdefghi"};
    for (i = 0; i < sizeof(src) / sizeof(src[0]); i++) {
        encode = base64_encode(src[i], strlen(src[i]));
        printf("  encode(\"%s\") => %s\n", src[i], encode);

        int decode_len = 0;
        decode = base64_decode(encode, &decode_len);

        //因为解码出的数据是不带\0结束符的，所以如果原文内容是字符串，需要自行构建字符串来使用，以便读取到不可预期数据。
        //如果原文内容为二进制数据，则不需要该步骤
        char *decode_string = strndup(decode, decode_len);
        printf("  decode(\"%s\") => %s\n", encode, decode_string);

        free(decode_string);

        free(encode);
        encode = NULL;

        free(decode);
        decode = NULL;
    }
}
